home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / terms / tip / slip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-14  |  5.2 KB  |  233 lines

  1. #ifndef lint
  2. static char *sccsid = "%W%    MS/ACF    %E%";
  3. #endif
  4. /*
  5.  *  tip/slip.c
  6.  *
  7.  *  This file contains the SLIP specific startup code.  It is designed
  8.  *  with both BSD sockets and Sun Streams in mind, though the socket
  9.  *  version has not been tested lately (but it SHOULD work).  The Streams
  10.  *  code is for SunOS 4.0[.1].
  11.  *
  12.  *  The code to set the route (basically an internal shell script) may
  13.  *  need tweeking on other systems, though it works on any of the
  14.  *  systems I have run into.
  15.  *
  16.  *  The alarm/DCD code is a HACK to detect loss of the line in the
  17.  *  absense of proper modems status signaling (broken in SunOS when
  18.  *  using the dialout device, serial line minor devices 128-255).
  19.  *  This has been reported, but I suspect that a fix will have to
  20.  *  wait for SunOS 4.2 or maybe 4.1.?.
  21.  *
  22.  *  Doug Kingston <dpk@morgan.com>
  23.  *  880219
  24.  */
  25.  
  26. #include "tip.h"
  27.  
  28. #include <sys/socket.h>
  29. #ifdef STREAMS
  30. #include <sys/stropts.h>
  31. #include <sys/sockio.h>
  32. #include <sys/termios.h>    /* has defines that clash with ioctl.h */
  33. #include <sys/slip.h>
  34. #endif STREAMS
  35. #include <netinet/in.h>
  36. #include <net/if.h>
  37.  
  38. #include <arpa/inet.h>
  39.  
  40. #define    DCD_SETTLING_TIME 1    /* time between DCD change and status check */
  41. #define    DCD_CHECK_INTERVAL 15    /* if > 0, time between automatic DCD checks */
  42.  
  43. int gotsig = 0;
  44. sigfunc_t dcd_handler();
  45.  
  46. runslip()
  47. {
  48.     int unit, s;
  49.     struct ifreq ifr;
  50. #ifdef I_POP /* Using streams */
  51.     struct termios tios;
  52.  
  53.     /* pop all streams modules */
  54.     while (ioctl(FD, I_POP, 0) == 0)
  55.         continue;
  56.  
  57.     /* set up the line parameters */
  58.     if (ioctl(FD, TCGETS, (caddr_t)&tios) < 0) {
  59.         perror("ioctl (TCGETS)");
  60.         return(1);
  61.     }
  62.     tios.c_cflag = (tios.c_cflag&(CBAUD|CIBAUD))|CS8|CREAD|HUPCL;
  63.     tios.c_iflag = IGNBRK;
  64.     if (ioctl(FD, TCSETS, (caddr_t)&tios) < 0) {
  65.         perror("ioctl (TCSETS)");
  66.         return(1);
  67.     }
  68.  
  69.     /* push the SLIP module */
  70.     if (ioctl(FD, I_PUSH, "slip") < 0) {
  71.         perror("ioctl (I_PUSH)");
  72.         return(1);
  73.     }
  74.  
  75.     /* find out what unit number we were assigned */
  76.     if (ioctl(FD, SLIOGUNIT, (caddr_t)&unit) < 0) {
  77.         perror("ioctl (SLIOGUNIT)");
  78.         return(1);
  79.     }
  80. #else /* not streams */
  81.     int ldisc = SLIPDISC;
  82.     if (ioctl(FD, TIOCSETD, &ldisc) < 0) {
  83.         perror("slipd: TIOCSETD");
  84.         return(1);
  85.     }
  86.     if (ioctl(FD, TIOCGETD, &unit) < 0) {    /* Hack to get slip number */
  87.         perror("slipd: TIOCGETD");
  88.         return(1);
  89.     }
  90. #endif I_POP
  91.  
  92.     /* set the local and remote interface addresses */
  93.     s = socket(AF_INET, SOCK_DGRAM, 0);
  94.  
  95.     (void) sprintf(ifr.ifr_name, "slip%d", unit);
  96.     if (in_getaddr(DA, &ifr.ifr_addr) != 0 ||
  97.         ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) {
  98.         perror("ioctl (SIOCSIFDSTADDR)");
  99.         return(1);
  100.     }
  101.  
  102.     /* this has the side-effect of marking the interface up */
  103.     if (in_getaddr(SA, &ifr.ifr_addr) != 0 ||
  104.         ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) {
  105.         perror("ioctl (SIOCSIFADDR)");
  106.         return(1);
  107.     }
  108.  
  109.     if (in_getaddr(SM, &ifr.ifr_addr) != 0) {
  110.         if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) {
  111.             perror("ioctl (SIOCSIFADDR)");
  112.             return(1);
  113.         }
  114.     }
  115.  
  116.     /* Set up default route if desired and not already present */
  117.     if (boolean(value(SETROUTE))) {
  118.         char buf[256];
  119.         char *argv[4];
  120.         char *envp[2];
  121.         int status;
  122.  
  123.         sprintf(buf, "if eval 'netstat -r|grep -s \"^default\"';\
  124.                   then echo default route already installed;\
  125.                   else route add 0 %s 3; fi", SA);
  126.         argv[0] = "/bin/sh";
  127.         argv[1] = "-c";
  128.         argv[2] = buf;
  129.         argv[3] = (char *)0;
  130.  
  131.         envp[0] = "PATH=/bin:/usr/bin:/usr/ucb:/etc:/usr/etc";
  132.         envp[1] = (char *)0;
  133.  
  134.         switch (fork()) {
  135.         case 0:        /* Child */
  136.             execve(argv[0], argv, envp);
  137.             exit(1);
  138.         case -1:
  139.             perror("tip: route add: fork");
  140.             break;
  141.         default:    /* Parent */
  142.             wait(&status);
  143.         }
  144.     }
  145.  
  146.     fprintf(stderr, "\07[SLIP running]\r\n");
  147.  
  148.     /* set up signal handlers */
  149.     (void) sigblock(sigmask(SIGALRM));
  150.     (void) signal(SIGALRM, dcd_handler);
  151. #if defined(SIGDCD) && SIGDCD > 0
  152.     (void) signal(SIGDCD, dcd_handler);
  153. #endif
  154.  
  155.     /* twiddle thumbs until we get a signal */
  156.     while (1) {
  157.         alarm(DCD_CHECK_INTERVAL);
  158.         sigpause(0);
  159. #if defined(SIGDCD) && SIGDCD > 0
  160.         (void) sigblock(sigmask(SIGALRM)|sigmask(SIGDCD));
  161. #else
  162.         (void) sigblock(sigmask(SIGALRM));
  163. #endif SIGDCD
  164.         if (gotsig && lowdcd(FD)) {
  165.             sleep(DCD_SETTLING_TIME);
  166.             if (lowdcd(FD))
  167.                 break;
  168.         }
  169.         gotsig = 0;
  170.     }
  171.     return(0);
  172. }
  173.  
  174. abort_slip()
  175. {
  176. #ifdef STREAMS
  177.     /* pop the SLIP stream module */
  178.     while(ioctl(FD, I_POP, 0) == 0);
  179. #else
  180.     int ldisc = 0;
  181.     (void)ioctl(FD, TIOCSETD, &ldisc);
  182. #endif
  183. }
  184.  
  185. sigfunc_t
  186. dcd_handler()
  187. {
  188.     gotsig = 1;
  189. }
  190.  
  191. /* Use TIOCMGET to test if DCD is low on the port of the passed descriptor */
  192. int
  193. lowdcd(fd)
  194.     int fd;
  195. {
  196.     int mbits;
  197.  
  198.     if (ioctl(fd, TIOCMGET, (caddr_t)&mbits) < 0)
  199.         return 1;    /* port is dead, we die */
  200.     return !(mbits & TIOCM_CAR);
  201. }
  202.  
  203. in_getaddr(s, saddr)
  204.     char *s;
  205.     struct sockaddr *saddr;
  206. {
  207.     register struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
  208.     struct hostent *hp;
  209.     struct netent *np;
  210.     int val;
  211.  
  212.     sin->sin_family = AF_INET;
  213.     val = inet_addr(s);
  214.     if (val != -1) {
  215.         sin->sin_addr.s_addr = val;
  216.         return(0);
  217.     }
  218.     hp = gethostbyname(s);
  219.     if (hp) {
  220.         sin->sin_family = hp->h_addrtype;
  221.         bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
  222.         return(0);
  223.     }
  224.     np = getnetbyname(s);
  225.     if (np) {
  226.         sin->sin_family = np->n_addrtype;
  227.         sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
  228.         return(0);
  229.     }
  230.     fprintf(stderr, "tip: in_getaddr: can't parse/lookup '%s'\n", s);
  231.     return(1);
  232. }
  233.